package codegen.groovy.graphnetwork.graphics

import java.awt.Cursor
import groovy.swing.j2d.GraphicsBuilder
import javax.swing.JComponent;
import codegen.graphnetwork.model.*
import groovy.swing.j2d.GraphicsOperation
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.transform.MutableTransformer;
import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator;
import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;
import java.awt.geom.Point2D
import edu.uci.ics.jung.visualization.RenderContext

public class NodeDisplay{
    def Node n;
    // Display const
    static def vh=20;
    static def vr=4;
    static def nw=180;
    static def nth=15;
    public final static Cursor busyCursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
    public final static Cursor moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
    public final static Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
    def parent;
    def borderOn = { e -> e.target.borderColor = 'red'; parent.parent.setCursor(moveCursor) }
    def borderOff = { e -> e.target.borderColor = false; parent.parent.setCursor(defaultCursor); }
    boolean selected;
    def dx,dy;
    def ox,oy;
    def dragging = 0;
    Layout layout;
    RenderContext rc;
    def mouseDrag={e->
        if (dragging==0){
            dx = e.event.x
            dy = e.event.y
            ox = n.x
            oy = n.y
            dragging = 1;
            println "Dragging ==1"
        }

        
    }
    
    def mouseMoving={e->
        if (dragging==1){
            n.x = ox+(e.event.x - dx)
            n.y = oy+(e.event.y - dy)
            //println n.x + " " + n.y
            update()
            
        }
        println "Moving"
    }
    def mouseClicked ={e->
        this.selected = true;
        gb.'outline'.borderColor ='red'
        println this.n.name;
        
        def shape = e.target
        //def bounds = shape.area.bounds
        //def location = shape.props.location
        if (dragging==0){
            dx = e.event.x
            dy = e.event.y
            ox = n.x
            oy = n.y
            dragging = 1;
            println "Dragging ==1"
        } else {
            dragging = 0
        }
    }
    def mousePressed ={e->


    }
    def endDrag={e->
        //dragging = 0
        //println "Dragging ==0"
    }
    GraphicsBuilder gb = new GraphicsBuilder()
    
    public NodeDisplay(n,RenderContext rc,Layout layout){
        this.n = n;
        this.layout = layout;
        this.rc = rc;
    }
    
    public static def getNodeSize(Node n){
        def ni=n.inputs;
        def no=n.outputs;
        def numOfLines = (ni.size()>=no.size())?ni.size():no.size();
        def nh=vh*(numOfLines+2)
        
        return [w:nw,h:nh,x:n.x,y:n.y,num:numOfLines]
    }
    
    public GraphicsOperation getNodeShape(){
        def ni=n.inputs;
        def no=n.outputs;
        def size=getNodeSize(n)
        def nh=size.h
        Point2D lpos = layout.transform(n);
        lpos = rc.getMultiLayerTransformer().transform(Layer.LAYOUT, lpos);
        n.x = lpos.x;
        n.y = lpos.y;

        def go = gb.group {
            
            // Rect shape
            rect(id:'outline', x: n.x, y: n.y, width: nw, height: nh, borderColor: 'black', borderWidth: 1,fill: 'lightGray')
            rect(id:'titlePanel', x: n.x+2, y: n.y+2, width: nw-4, height: nth, arcWidth: 10, arcHeight: 10, borderColor: 'darkRed', borderWidth: 1, fill: 'white' 
                ,mouseEntered:borderOn,mouseExited:borderOff,mouseDragged: mouseDrag,mouseReleased:endDrag,mouseClicked:mouseClicked,mousePressed:mousePressed,mouseMoved:mouseMoving)
            //font( face: "Helvetica", style: Font.ITALIC, size: 12 )
            // Title
            text(id:'titleText', text: n.name, x: n.x+10, y: n.y + 4, borderColor: false, fill: 'black' )
            def statusColor
            
            switch (n.status){
                case Node.Status.Init:
                statusColor = 'red'
                break
                case Node.Status.Computing:
                statusColor = 'yellow'
                break
                case Node.Status.Finished:
                statusColor = 'green'
                break
            }
            rect(id:'outline', x: n.x, y: n.y, width: 8, height: nth, borderColor: 'black', borderWidth: 1,fill: statusColor)
            ni.eachWithIndex{value,i->
                def tx=n.x
                def ty=n.y+vh*(i+1)
                circle(id:'iValueCircle'+i, cx: tx, cy: ty, radius: vr, borderColor: 'darkgray', borderWidth:1, fill: 'yellow' )
                text(id:'iValueText'+i, text: value.name+"("+value.value+")", x: tx+5, y: ty, borderColor: false,fill: 'black' )
                
            }
            no.eachWithIndex{value,i->
                def tx=n.x+nw
                def ty=n.y+vh*(i+1)
                circle(id:'oValueCircle'+i, cx: tx, cy: ty, radius: vr, borderColor: 'darkgray', borderWidth:1, fill: 'cyan' )
                text(id:'oValueText'+i, text: value.name+"("+value.value+")", x: tx-nw/2, y: ty, borderColor: false,fill: 'black' )
                
            }
        }
        println "Called!";
        return go;
    }
    def update(){
        /*
        def ni=n.inputs;
        def no=n.outputs;
        gb.'outline'.x=n.x
        gb.'outline'.y=n.y
        
        gb.'titlePanel'.x= n.x+2 
        gb.'titlePanel'.y= n.y+2
        
        gb.'titleText'.x= n.x+10
        gb.'titleText'.y= n.y + 4
        
        ni.eachWithIndex{value,i->
        def tx=n.x
        def ty=n.y+vh*(i+1)
        gb.('iValueCircle'+i).cx= tx
        gb.('iValueCircle'+i).cy= ty
             
        gb.('iValueText'+i).x= tx+5
        gb.('iValueText'+i).y= ty
                
        }
        no.eachWithIndex{value,i->
        def tx=n.x+nw
        def ty=n.y+vh*(i+1)
        gb.('oValueCircle'+i).cx= tx
        gb.('oValueCircle'+i).cy= ty
        gb.('oValueText'+i).x= tx-nw/2
        gb.('oValueText'+i).y= ty
                
        }
         */
        
        parent.update()
    }
    public static def getValueSize(Value v){

        if (v.isInput){
            def list = v.parent.inputs
            def index=list.indexOf(v)
            
            return [x:0,y:vh*(index+1)]
        } else {
            def list = v.parent.outputs
            def index=list.indexOf(v)
            
            return [x:nw,y:vh*(index+1)]
        }      
        
        
    }
}
